//
//  NSNotificationCenter+DebugManager.m
//  YK_DebugManager
//
//  Created by edward on 2021/10/21.
//

#import "NSNotificationCenter+DebugManager.h"
#import "DebugNotificationManager.h"
#import <objc/message.h>

@implementation NSNotificationCenter (DebugManager)

+ (void)load
{
    //因为是类方法所以要调用class_getClassMethod方法进行获取方法的Method
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method method_add = class_getInstanceMethod([self class], @selector(addObserver:selector:name:object:));
        Method debugmethod_add = class_getInstanceMethod([self class], @selector(debugManager_addObserver:selector:name:object:));
        method_exchangeImplementations(method_add, debugmethod_add);
        
        Method method = class_getInstanceMethod([self class], @selector(postNotification:));
        Method debugmethod = class_getInstanceMethod([self class], @selector(debugManager_postNotification:));
        method_exchangeImplementations(method, debugmethod);
        
        Method emethod = class_getInstanceMethod([self class], @selector(postNotificationName:object:));
        Method debugemethod = class_getInstanceMethod([self class], @selector(debugManager_postNotificationName:object:));
        method_exchangeImplementations(emethod, debugemethod);
        
        Method bmethod = class_getInstanceMethod([self class], @selector(postNotificationName:object:userInfo:));
        Method debugbmethod = class_getInstanceMethod([self class], @selector(debugManager_postNotificationName:object:userInfo:));
        method_exchangeImplementations(bmethod, debugbmethod);
        
        Method method_rem = class_getInstanceMethod([self class], @selector(removeObserver:));
        Method debugbmethod_rem = class_getInstanceMethod([self class], @selector(debugManager_removeObserver:));
        method_exchangeImplementations(method_rem, debugbmethod_rem);
        
        Method method_rem_name = class_getInstanceMethod([self class], @selector(removeObserver:name:object:));
        Method debugbmethod_rem_name = class_getInstanceMethod([self class], @selector(debugManager_removeObserver:name:object:));
        method_exchangeImplementations(method_rem_name, debugbmethod_rem_name);
        
        Method method_add_block = class_getInstanceMethod([self class], @selector(addObserverForName:object:queue:usingBlock:));
        Method debugbmethod_add_block = class_getInstanceMethod([self class], @selector(debugManager_addObserverForName:object:queue:usingBlock:));
        method_exchangeImplementations(method_add_block, debugbmethod_add_block);
    });
    
}

- (void)debugManager_addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject
{
    [self addListType:0 name:aName object:anObject userInfo:@{@"observer":observer?:@"",@"selector":NSStringFromSelector(aSelector),@"time":[NSDate date]}];
    [self debugManager_addObserver:observer selector:aSelector name:aName object:anObject];
}

- (id<NSObject>)debugManager_addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block
{
    [self addListType:1 name:name object:obj userInfo:@{@"queue":queue?:@"",@"time":[NSDate date]}];
    return [self debugManager_addObserverForName:name object:obj queue:queue usingBlock:block];
}

- (void)debugManager_postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo
{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setValuesForKeysWithDictionary:aUserInfo];
    [dic setValue:[NSDate date] forKey:@"time"];
    [self addListType:2 name:aName object:anObject userInfo:dic.copy];
    [self debugManager_postNotificationName:aName object:anObject userInfo:aUserInfo];
}

- (void)debugManager_postNotificationName:(NSNotificationName)aName object:(nullable id)anObject
{
    [self addListType:3 name:aName object:anObject userInfo:@{@"time":[NSDate date]}];
    [self debugManager_postNotificationName:aName object:anObject];
}

- (void)debugManager_postNotification:(NSNotification *)notification
{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setValuesForKeysWithDictionary:notification.userInfo];
    [dic setValue:[NSDate date] forKey:@"time"];
    [self addListType:4 name:notification.name object:notification.object userInfo:dic.copy];
    [self debugManager_postNotification:notification];
}

- (void)debugManager_removeObserver:(id)observer
{
    [self addListType:5 name:nil object:nil userInfo:@{@"observer":observer?:@"",@"time":[NSDate date]}];
    [self debugManager_removeObserver:observer];
}

- (void)debugManager_removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObject
{
    [self addListType:6 name:aName object:anObject userInfo:@{@"observer":observer?:@"",@"time":[NSDate date]}];
    [self debugManager_removeObserver:observer name:aName object:anObject];
}

- (void)addListType:(NSInteger)type name:(nullable NSNotificationName)name object:(nullable id)object userInfo:(nullable NSDictionary *)userInfo
{
    if ([DebugNotificationManager sharedInstance].isRecordNotification) {
        [[DebugNotificationManager sharedInstance] addListType:type name:name object:object userInfo:userInfo];
    }
}

@end
